using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NAudio.Wave;
using AudioInterface;

namespace MKDS_Course_Editor.sbnk
{
    partial class DLS : Form
    {
        sseq.Sbnk file;
        //Declarations required for audio out and mixing
        private static IWavePlayer waveOutDevice;
        private static WaveMixerStream32 mixer;

        // The Sample array we will load our Audio Samples in to
        private static AudioSample[] Sample;

        public DLS(sseq.Sbnk bnk)
        {
            file = bnk;
            InitializeComponent();
        }

        private void DLS_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < file.Data.nCount; i++)
            {
                if (file.Data.Ins[i].fRecord == 0) continue;
                if (file.Data.Ins[i].fRecord < 16)
                {
                    sseq.iRecord_16 info = (sseq.iRecord_16)file.Data.Ins[i].iInfo;
                    TreeNode t = treeView1.Nodes.Add("("+i.ToString("000")+"):Single Region Instrument");
                    t.Tag = info;
                    t.Nodes.Add("0-127");
                }
                else if (file.Data.Ins[i].fRecord == 16)
                {
                    sseq.iRecord16 info = (sseq.iRecord16)file.Data.Ins[i].iInfo;
                    TreeNode t = treeView1.Nodes.Add("(" + i.ToString("000") + "):Multi Region Instrument");
                    t.Tag = info;
                    for (int j = 0; j < info.uNote - info.lNote + 1; j++)
                    {
                        TreeNode k = t.Nodes.Add((info.lNote+j).ToString());
                        k.Tag = info.Info[j];
                    }
                }
                else if (file.Data.Ins[i].fRecord == 17)
                {
                    sseq.iRecord17 info = (sseq.iRecord17)file.Data.Ins[i].iInfo;
                    TreeNode t = treeView1.Nodes.Add("(" + i.ToString("000") + "):Multi Region Instrument");
                    t.Tag = info;
                    for (int j = 0; j < info.nr; j++)
                    {
                        TreeNode k = t.Nodes.Add((j == 0 ? 0 : info.Regions[j - 1] + 1)+"-"+info.Regions[j]);
                        k.Tag = info.Info[j];
                    }
                }
            }
            SetupAudio(1);
        }

        private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Node.Parent != null)
            {
                byte[] m = null;
                double pan = 0;
                if (e.Node.Parent.Tag is sseq.iRecord_16)
                {
                    sseq.iRecord_16 info = (sseq.iRecord_16)e.Node.Parent.Tag;
                    pan = info.RealPan;
                    SDAT.WAV.ArchivoWAV aww = SDAT.SWAV.ConvertirAWAV(info.WaveData);
                    waveViewer1.SamplesPerPixel = aww.wave.data.data.Length / (aww.wave.fmt.bitsPerSample / 8)/waveViewer1.Width;
                    waveViewer1.WaveStream = new NAudio.Wave.WaveFileReader(new System.IO.MemoryStream(SDAT.WAV.EscribirArchivo(aww)));
                    m = SDAT.WAV.EscribirArchivo(aww);
                    timeLine1.PixelsPerSecond = (double)timeLine1.Width / waveViewer1.WaveStream.TotalTime.TotalSeconds;
                }
                else if (e.Node.Parent.Tag is sseq.iRecord16)
                {
                    sseq.iRecord16.info info = (sseq.iRecord16.info)e.Node.Tag;
                    pan = info.RealPan;
                    SDAT.WAV.ArchivoWAV aww = SDAT.SWAV.ConvertirAWAV(info.WaveData);
                    waveViewer1.SamplesPerPixel = aww.wave.data.data.Length / (aww.wave.fmt.bitsPerSample / 8) / waveViewer1.Width;
                    waveViewer1.WaveStream = new NAudio.Wave.WaveFileReader(new System.IO.MemoryStream(SDAT.WAV.EscribirArchivo(aww)));
                    m = SDAT.WAV.EscribirArchivo(aww);
                    timeLine1.PixelsPerSecond = (double)timeLine1.Width / waveViewer1.WaveStream.TotalTime.TotalSeconds;
                }
                else if (e.Node.Parent.Tag is sseq.iRecord17)
                {
                    sseq.iRecord17.info info = (sseq.iRecord17.info)e.Node.Tag;
                    pan = info.RealPan;
                    SDAT.WAV.ArchivoWAV aww = SDAT.SWAV.ConvertirAWAV(info.WaveData);
                    waveViewer1.SamplesPerPixel = aww.wave.data.data.Length / (aww.wave.fmt.bitsPerSample / 8) / waveViewer1.Width;
                    waveViewer1.WaveStream = new NAudio.Wave.WaveFileReader(new System.IO.MemoryStream(SDAT.WAV.EscribirArchivo(aww)));
                    m = SDAT.WAV.EscribirArchivo(aww);
                    timeLine1.PixelsPerSecond = (double)timeLine1.Width / waveViewer1.WaveStream.TotalTime.TotalSeconds;
                }
                toolStripButton3.Enabled = toolStripButton4.Enabled = true;
                LoadSample(new NAudio.Wave.WaveFileReader(new System.IO.MemoryStream(m)), 0);
                Sample[0].SetPan((float)pan);
            }
        }
        /// <summary>
        /// Setup Audio via NAudio. 
        /// Defaults to using Asio for Audio Output.
        /// </summary>
        public void SetupAudio(int Samples)
        {
            //Setup the Mixer
            mixer = new WaveMixerStream32();
            mixer.AutoStop = false;
            
            if (waveOutDevice == null)
            {
                waveOutDevice = new DirectSoundOut();
                waveOutDevice.Init(mixer);
                waveOutDevice.Play();
            }

            Sample = new AudioSample[Samples];
        }
        public void LoadSample(WaveStream fileName, int sampleNumber)
        {
            if (Sample[sampleNumber] != null)
            {
                mixer.RemoveInputStream(Sample[sampleNumber]);
            }
            Sample[sampleNumber] = new AudioSample(fileName);
            // Need to dispose the waveOutDevice - if it is created before the sample has been added
            // to the mixer then sample playback is undertaken at twice the speed for some reason
            waveOutDevice.Dispose();
            // Add the stream to the mixer
            mixer.AddInputStream(Sample[sampleNumber]);
            //Re-initalise the waveOutDevice and play back sound
            waveOutDevice = new DirectSoundOut();
            waveOutDevice.Init(mixer);
            waveOutDevice.Play();

            // The stop is required because when an InputStream 
            // is added, if it is too long it will start 
            // playing because we do not turn off the mixer.
            // This is effectively just a work around by making
            // sure that we move the playback position 
            // to the end of the stream to aviod this issue.
            Stop(sampleNumber);
        }
        public void Stop(int sampleNumber)
        {
            // Set the position at the end of the sample length
            Sample[sampleNumber].Position = Sample[sampleNumber].Length;
        }
        public void Play(int sampleNumber)
        {
            Sample[sampleNumber].Position = 0;
        }
        public void Pause(int sampleNumber)
        {
            Sample[sampleNumber].Pause();
        }

        public void Resume(int sampleNumber)
        {
            Sample[sampleNumber].Resume();
        }
        private void waveViewer1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            if ((string)(toolStripButton3.Tag) == "play")
            {
                Play(0);
                toolStripButton3.Image = Properties.Resources.control_pause;
                toolStripButton3.Tag = "pause";
            }
            else
            {
                Pause(0);
                toolStripButton3.Image = Properties.Resources.control;
                toolStripButton3.Tag = "play";
            }
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            Stop(0);
        }

        private void DLS_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (Sample[0] != null)
            {
                mixer.RemoveInputStream(Sample[0]);
                Sample[0].Close();
            }
            mixer.Dispose();
            mixer.Close();
            waveOutDevice.Stop();
            waveOutDevice.Dispose();
            mixer = null;
            waveOutDevice = null;
            Sample = null;
            timer1.Stop();
            timer1.Enabled = false;
            timer1 = null;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (Sample[0] != null)
            {
                if (Sample[0].Position >= Sample[0].Length)
                {
                    toolStripButton3.Image = Properties.Resources.control;
                    toolStripButton3.Tag = "play";
                }
                else
                {
                    timeLine1.NowTime = Sample[0].CurrentTime;
                }
            }
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && saveFileDialog1.FileName.Length > 0)
            {
                sseq.writeDLS(saveFileDialog1.FileName, file);
            }
        }

        private string GetInstrument(int idex)
        {
            switch (idex)
            {
                case 127:
                    return "Drums";
            }
            return "Unknown";
        }
    }
}
